package concurrecy.util;

import java.util.Random;
import java.util.concurrent.*;

class DelayTask implements Delayed {
    private long trigger;
    private long delay;
    private static int count = 0;
    private final int id = count ++;

    public DelayTask(long delay) {
        this.delay = delay;
        this.trigger = System.currentTimeMillis() + delay;
    }

    @Override
    public int compareTo(Delayed o) {
        return Long.compare(this.trigger, ((DelayTask) o).trigger);
    }

    public void run() {
        System.out.printf("[%-2d] [%-5d] - run\n", id, delay);
    }

    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert(trigger - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
    }
}

class DelayTaskTerminator extends DelayTask {

    private ExecutorService service;
    public DelayTaskTerminator(long delay, ExecutorService service) {
        super(delay);
        this.service = service;
    }

    @Override
    public void run() {
        super.run();
        System.out.println("shutdown");
        service.shutdownNow();
    }
}

/**
 * Delay Queue
 */
public class DelayQueueDemo {
    public static void main(String[] args) {
        ExecutorService service = Executors.newCachedThreadPool();
        final DelayQueue<DelayTask> delayTasks = new DelayQueue<>();
        Random random = new Random();
        for (int i = 0; i < 20; i++) {
            delayTasks.put(new DelayTask(random.nextInt(5000)));
        }

        delayTasks.put(new DelayTaskTerminator(6000, service));

        service.execute(() -> {
            try {
                while (!Thread.interrupted()) {
                    delayTasks.take().run();
                }
            } catch(InterruptedException e) {
                System.out.println("consumer interrupted");
            }
            System.out.println("consumer exit");
        });
    }
}
